#include "deck.h"

Deck::Deck()//构造函数初始化了m_deck数组
{
    for(int i=0;i<52;i++)
    {
        isOut[i]= true;
    }
    CardScene=new mScene;
    for(int i=0;i<=3;i++)
    {
        for(int j=1;j<=13;j++)
        {
            m_deck.emplace_back(i,j);
        }
    }
}
int Deck::getRandom(int min, int max)
{
    static std::mt19937 rng(std::random_device{}());
    return std::uniform_int_distribution<>(min, max)(rng);
}
void Deck::createCardImage(int i,const QPointF& pos, Card card)
{
    isOut[13*(card.suit())+card.rank()-1]= false;//打出的牌标记为false
    //path为图片的路径
    QString path = QString(":/new/prefix2/PokerCard/%1_%2.jpg").arg(card.suit()).arg(card.rank(), 2, 10, QChar('0'));
    HandCards.append(new CardItem(QPixmap(path),13*(card.suit())+card.rank()-1,i));
    CardScene->mScene2->addItem(HandCards[i]);
    HandCards[i]->setPos(pos);
    HandCards[i]->setZValue(1);
}
void Deck::dealCards()
{
    int x = 200, y = 700; // 起始位置
    QVector<int> randomRank;
    //获得不重复的随机数并存储在上列数组中
    generateRandomRankOriginal(randomRank,8);
    for(int i = 0; i < 8; i++)
    { // 给玩家发8张牌
        createCardImage(i,QPointF(x + i*170,y), m_deck[randomRank[i]]);
    }
}
void Deck::InReady()
{
    //将被点击的卡牌加入准备区
    int ReadySize=ReadyCards.size();
    if(ReadySize==0)
    {
        for(int i=0;i<8;i++)
        {
            if(HandCards[i]->m_isLifted)
            {
               ReadyCards.append(HandCards[i]);
            }
        }
    }
    //判断准备区是否已有卡牌，若有则删除再添加
    else
    {
        ReadyCards.clear();
        InReady();
    }
}
void Deck::InAlready()//出牌函数
{
    //InReady();//加入准备区
    int ReadySize=ReadyCards.size();
    //判分系统
    QVector<int> ReadyCardsPoints;
    for(int i=0;i<ReadySize;i++)
    {
        ReadyCardsPoints+=ReadyCards[i]->ending;
    }
    QString HandName=m_JudgeCard->detectHandName(ReadyCardsPoints);
    int HandScore=m_JudgeCard->detectHandScore(ReadyCardsPoints);
    Utils_1->showFloatingText(CardScene->mScene2,"恭喜您打出了"+HandName,QPointF(730,300),2000);
    Utils_1->showFloatingText(CardScene->mScene2,QString::number(HandScore),QPointF(730,350),2000);
    TheScore+=HandScore;
    PublicFun();
}
void Deck::OutAlready()//弃牌函数
{
    InReady();
    PublicFun();
}
void Deck::PublicFun()//出牌弃牌公用函数
{
    //获取出牌的相对位置和绝对位置
    int ReadySize=ReadyCards.size();
    QVector<int> ReadyNum;
    QVector<QPointF> ReadyPos;
    for(int i=0;i<ReadySize;i++)
    {
        ReadyNum.append(ReadyCards[i]->n);
        ReadyPos.append(ReadyCards[i]->pos());
    }
    BubbleSort(ReadyNum);
    for(int i=0;i<ReadySize;i++)
    {
        CardScene->mScene2->removeItem(ReadyCards[i]);
    }
    QVector<int> randomRank;
    for(int i=0;i<ReadySize;i++)
    {
        HandCards.removeAt(ReadyNum[i]);//删除手牌中的准备区的牌
    }
    //获得不重复的随机数并存储在上列数组中
    generateRandomRankOriginal(randomRank,ReadySize);
    for(int i = 0; i < ReadySize; i++)
    { // 给玩家重新发张牌
        // 获取当前的y值并加上变化量
        qreal newY = ReadyPos[i].y() + 40;

        // 设置新的y值
        ReadyPos[i].setY(newY);

        createCardImage(8-ReadySize+i, ReadyPos[i], m_deck[randomRank[i]]);//同时加入手牌
    }
    for(int i=0;i<8;i++)
    {
        HandCards[i]->n= i;
    }
}
void Deck::generateRandomRankOriginal(QVector<int>& vec,int n)//生成随机数数组
{
    int count = 0;
    for(int i = 0; i < 52; ++i)//统计可用牌数
    {
        if(isOut[i]) count++;
    }

    for(int i = 0; i < n; i++)
    {
        bool found = false;
        int safety = 0;

        while(!found && safety++ < 1000)
        {
            int temp = getRandom(0, 51);

            // 条件1：必须为可用牌
            if(!isOut[temp]) continue;

            // 条件2：不能重复
            bool duplicate = false;
            for(int j = 0; j < i; j++)
            {
                if(temp == vec[j])
                {
                    duplicate = true;
                    break;
                }
            }

            if(!duplicate)
            {
                vec.append(temp);
                found = true;
            }
        }

        if(!found)
        {
            throw std::runtime_error("未能找到足够可用牌");
        }
    }
}
void Deck::BubbleSort(QVector<int>& vec)
{
    int n=vec.size();
    bool swapped;
    for (int i = 0; i < n - 1; i++) {
        swapped = false;
        // 最后i个元素已经是排序好的了
        for (int j = 0; j < n - 1 - i; j++) {
            if (vec[j] < vec[j + 1]) {
                // 交换相邻元素
                std::swap(vec[j], vec[j + 1]);
                swapped = true;
            }
        }
        // 如果没有发生交换，说明数组已经排序完成
        if (!swapped) break;
    }
}
